

import datetime
import json
import os
from pathlib import Path
from loguru import logger
from pygerrit2 import GerritRestAPI, HTTPBasicAuth
import requests
from config import AppConfig, HTTP_SUCCESS
from flask import Flask, render_template



class DifyClient:
    def __init__(self, appConfig:AppConfig):
        self.dify_api_test_key = appConfig.dify_api_test_key
        self.dify_api_key = appConfig.dify_api_key
        self.dify_api_server = appConfig.dify_api_server

    def workflow_run(self, code_changes:str, options:dict):
        """
        运行工作流
        
        Args:
            code_changes (str): 代码变更内容
            options (dict): 选项参数
            
        Returns:
            dict: 工作流执行结果
        """
        if 'prompt' in options:
            headers = {
                'Authorization': 'Bearer ' + self.dify_api_test_key, 
                'Content-Type': 'application/json'  
            }
            parm = {
                "inputs": {
                    "code_changes" : code_changes, 
                    "new_h_flag" : options['new_h_flag'],
                    "result_dir" : options['result_dir'],
                    "check_rules" : options['prompt'],
                    }, 
                "user" : "vluo", 
                "response_mode" : "blocking",
            }
        else:
            headers = {
                'Authorization': 'Bearer ' + self.dify_api_key, 
                'Content-Type': 'application/json'  
            }
            parm = {
                "inputs": {
                    "code_changes" : code_changes, 
                    "new_h_flag" : options['new_h_flag'],
                    "result_dir" : options['result_dir'],
                    }, 
                "user" : "vluo", 
                "response_mode" : "blocking",
            }
        try:
            ret = requests.post(f'{self.dify_api_server}/workflows/run', data=json.dumps(parm), headers=headers)
            response_data = ret.json()
            
            # 修复：检查工作流是否失败
            if response_data.get('data', {}).get('status') == 'failed':
                logger.info(f"工作流返回：{response_data}")
                if 'timeout' in response_data.get('data', {}).get('error'):
                    logger.error('工作流超时导致失败')
                    return 'workflow time out'
                else:
                    logger.error("工作流失败")
                    return None

            result = response_data.get('data', {}).get('outputs', {}).get('result')
            return result
        except Exception as e:
            logger.error(f"workflow_run error: {e}")
            logger.info(f"result: {ret.json()}")
            return None


class GerritClient:
    def __init__(self, appConfig:AppConfig):
        url = appConfig.gerrit_url
        auth = HTTPBasicAuth(appConfig.username, appConfig.password)
        self.gerrit_client = GerritRestAPI(url, auth)
        self.reports_path = appConfig.reportspath
        
    def get_change_info_from_gerrit(self, change_id):
        """
        从Gerrit获取变更信息
        
        Args:
            change_id (str): 变更ID
            
        Returns:
            dict: 变更信息
        """
        #  获取提交基本信息
        endpoint = f"/changes/{change_id}"
        basic_info = self.gerrit_client.get(endpoint)

        # 获取代码改动文件
        endpoint = f"/changes/{change_id}/revisions/current/files"
        changed_files = self.gerrit_client.get(endpoint)

        data = {
            "change_id": change_id,
            "basic_info": basic_info,
            "changed_files": changed_files
        }
        logger.info(data)
        return data
    def get_change_patch(self, change_id):
        """
        获取变更的补丁
        
        Args:
            change_id (str): 变更ID
            
        Returns:
            str: 补丁内容
        """
        endpoint = f"/changes/{change_id}/revisions/current/patch"
        patch = self.gerrit_client.get(endpoint)
        return patch

    def get_file_content(self, change_id, file_path : str):
        """
        获取文件内容
        
        Args:
            change_id (str): 变更ID
            file_path (str): 文件路径
            
        Returns:
            str: 文件内容
        """
        file_path = file_path.replace('/', '%2F')
        endpoint = f"/changes/{change_id}/revisions/current/files/{file_path}/content"
        file_content = self.gerrit_client.get(endpoint)

        # 返回的结果是str类型，换行符可能为windows或linux，splitlines统一处理
        file_lines = file_content.splitlines()
        result = []
        for _, s in enumerate(file_lines[:]) :
            result.append(s + '\n')

        return result

    def get_account_info_from_gerrit(self, account_id):
        """
        从Gerrit获取账户信息
        
        Args:
            account_id (str): 账户ID
            
        Returns:
            dict: 账户信息
        """
        endpoint = f"/accounts/{account_id}"
        account_info = self.gerrit_client.get(endpoint)

        data = {
            "account_id": account_id,
            "account_info": account_info
        }
        logger.info(data)
        return data

    def gerrit_code_review_auto(self, repo, change_number):
        """
        自动进行代码评审
        
        Args:
            repo (str): 仓库名称
            change_number (int): 变更编号
        """
        data = {
            "labels": {
                "Code-Review": 1
            },
            "message": "Automatically added +1 Code-Review vote."
        }

        endpoint = f"/changes/{repo}~{change_number}/revisions/current/review"
        response = self.gerrit_client.post(
            endpoint,
            return_response=True,
            json=data)

        if response[1].status_code == HTTP_SUCCESS:
            logger.info(f"Automatically added Code-Review successfully.")
        else:
            logger.info(
                f"Failed to add Code-Review Automatically. Status code: {response} {response[1]} {type(response[1])}")
            
    def gerrit_add_review_comment(self, repo, change_number, file_name):
        """
        在Gerrit中添加评审评论
        
        Args:
            repo (str): 仓库名称
            change_number (int): 变更编号
            file_name (str): 文件名
        """
        file_name = file_name + ".html"
        message = f"ErrorSniffer Analysis Report: {self.reports_path}/{file_name}"
        # 要发送的数据
        data = {
            "message": message
        }
        logger.info(f"reply in the gerrit:{message}!!!!")
        endpoint = f"/changes/{repo}~{change_number}/revisions/current/review"
        response = self.gerrit_client.post(
            endpoint,
            return_response=True,
            json=data)
            
        # 检查响应
        if response[1].status_code == HTTP_SUCCESS:
            logger.info("Change log message added successfully.", response)
        else:
            logger.info(f"Failed to add change log message. Status code: {response}")

    def generate_html_report(self, app:Flask, changes_number="", title="Gerrit 变更报告", output_path=None, data=None):
        """
        生成HTML报告
        
        Args:
            changes_number (str): 变更编号
            title (str): 报告标题
            output_path (str): 输出路径
            data (dict): 报告数据
            
        Returns:
            str: HTML内容
        """
        template_data = {
            'title': changes_number,
            'changeID': changes_number,
            'generated_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        with app.app_context():
            html_content = render_template('report_template.html', detail_data=data, **template_data)

        if output_path:
            # 确保目录存在
            output_path_obj = Path(output_path)
            if output_path_obj.suffix:  # 包含文件拓展名，为文件路径，则创建父目录
                output_path_obj.parent.mkdir(parents=True, exist_ok=True)
            else:  # 目录路径，则直接创建目录
                output_path_obj.mkdir(parents=True, exist_ok=True)

            # 如果output_path是目录，自动添加文件名
            if output_path_obj.is_dir() or str(output_path).endswith(os.sep):
                output_path_obj = output_path_obj / f"{title}.html"

            output_path_obj.write_text(html_content, encoding='utf-8')
            logger.info(f"HTML报告已生成: {output_path_obj}")

        return html_content
